/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.coreGenerator.base.serializer.changeser.dataType;

import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.caf.generator.utils.ExpressionUtils;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.gencommon.MediateType;
import com.inspur.edp.cef.generator.coreGenerator.base.mgrGenerator.ManagerGeneratorContext;
import com.inspur.edp.cef.spi.jsonser.builtinimpls.CefEntityDataSerializerItem;
import com.inspur.edp.cef.spi.jsonser.entity.AbstractEntitySerializerItem;
import org.eclipse.jdt.core.dom.*;

import java.util.ArrayList;
import java.util.List;

public class SerGetTypesGenerator extends ClassMethodGenerator {
    private static String varList = "list";
    protected ManagerGeneratorContext mgrContext;
    protected IGspCommonDataType dataType;

    public SerGetTypesGenerator(IGspCommonDataType dataType, ManagerGeneratorContext mgrContext) {
        this.dataType = dataType;
        this.mgrContext = mgrContext;
    }

    @Override
    protected Block buildMethodBody() {
        Block block = ast.newBlock();
        block.statements().add(createListDeclarationStatement());

        List<ExpressionStatement> expressionStatementList = createAddListItemsStatement();
        for (ExpressionStatement item : expressionStatementList) {
            block.statements().add(item);
        }
        block.statements().add(createReturnStatement());
        return block;
    }

    private VariableDeclarationStatement createListDeclarationStatement() {
        VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
        setListFragmentInfos(variableDeclarationFragment);
        VariableDeclarationStatement variableDeclarationStatement = ast.newVariableDeclarationStatement(variableDeclarationFragment);
        setListStatementType(variableDeclarationStatement);
        return variableDeclarationStatement;

    }

    private void setListStatementType(VariableDeclarationStatement variableDeclarationStatement) {
        ParameterizedType parameterizedType = ast.newParameterizedType(new TypeInfo(ArrayList.class).getType(ast));
        setListType(parameterizedType);
        addImport(AbstractEntitySerializerItem.class.getTypeName());
        variableDeclarationStatement.setType(parameterizedType);
    }

    private void setListFragmentInfos(VariableDeclarationFragment variableDeclarationFragment) {
        variableDeclarationFragment.setName(ast.newSimpleName(varList));
        ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
        ParameterizedType parameterizedType = ast.newParameterizedType(new com.inspur.edp.caf.generator.baseInfo.TypeInfo(ArrayList.class).getType(ast));
        classInstanceCreation.setType(parameterizedType);
        variableDeclarationFragment.setInitializer(classInstanceCreation);
    }

    protected void setListType(ParameterizedType parameterizedType) {
        parameterizedType.typeArguments().add(new com.inspur.edp.caf.generator.baseInfo.TypeInfo(AbstractEntitySerializerItem.class).getType(ast));
    }


    private List<ExpressionStatement> createAddListItemsStatement() {
        List<ExpressionStatement> list = new ArrayList<>();
        list.add(createAddListItemStatement());
        return list;
    }

    private ExpressionStatement createAddListItemStatement() {
        MethodInvocation addMethodInvocation = ast.newMethodInvocation();
        addMethodInvocation.setName(ast.newSimpleName("add"));
        addMethodInvocation.setExpression(ast.newSimpleName("list"));
        ClassInstanceCreation createItem = ast.newClassInstanceCreation();
        createItem.setType(ast.newSimpleType(ast.newName(getSerItemTypeName())));

        MediateType entityType = mgrContext.getProjContext().getEntityMediateTypes().get(dataType.getCode());

        MethodInvocation invocation = ExpressionUtils.getMethodInvocation(ast, entityType.getFullName(), "getResourceInfo");
        createItem.arguments().add(invocation);
        addMethodInvocation.arguments().add(createItem);
        return ast.newExpressionStatement(addMethodInvocation);
    }

    protected String getSerItemTypeName() {
        addImport(CefEntityDataSerializerItem.class.getTypeName());
        return CefEntityDataSerializerItem.class.getSimpleName();
    }

    private ReturnStatement createReturnStatement() {
        ReturnStatement returnStatement = ast.newReturnStatement();
        returnStatement.setExpression(ast.newSimpleName("list"));
        return returnStatement;
    }

    @Override
    protected ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
        ArrayList<Modifier.ModifierKeyword> list = new ArrayList<>();
        list.add(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
        list.add(Modifier.ModifierKeyword.STATIC_KEYWORD);
        return list;
    }

    @Override
    protected String getMethodName() {
        return "getTypes";
    }

    @Override
    protected ArrayList<ParameterInfo> getParameterCollection() {
        return new ArrayList<>();
    }

    @Override
    protected TypeInfo getReturnType() {
        TypeInfo typeInfo = new TypeInfo(ArrayList.class.getTypeName());
        typeInfo.setIsParameterizedType(true);
        typeInfo.getArguments().add(new TypeInfo(AbstractEntitySerializerItem.class));
        return typeInfo;
    }

}
